import ast
import logging
import time
from collections import defaultdict
from typing import Dict, List, Any

from 程序核心代码.ast节点.节点分析.分析器基类 import 分析器基类
from 程序核心代码.ast节点.节点定义.基础定义.ast节点基础定义 import ast节点基础模型

logger = logging.getLogger(__name__)

class 性能分析器(分析器基类):
    """性能分析器类，用于分析节点的性能特征和资源使用情况"""
    
    def __init__(self):
        super().__init__()
        self.执行时间: Dict[ast节点基础模型, float] = {}
        self.内存使用: Dict[ast节点基础模型, int] = {}
        self.复杂度估计: Dict[ast节点基础模型, str] = {}
        self.性能瓶颈: List[Dict[str, Any]] = []
        self.资源使用统计: Dict[str, Dict[str, float]] = defaultdict(lambda: defaultdict(float))
        
    def 分析节点(self, 节点: ast节点基础模型) -> Dict[str, Any]:
        """分析指定节点的性能特征"""
        try:
            if not self.验证节点(节点):
                return {}
                
            # 分析执行时间
            self._分析执行时间(节点)
            
            # 分析内存使用
            self._分析内存使用(节点)
            
            # 分析时间复杂度
            self._分析时间复杂度(节点)
            
            # 识别性能瓶颈
            self._识别性能瓶颈(节点)
            
            # 记录分析结果
            self.分析结果[节点._节点ID] = {
                "执行时间": self.执行时间.get(节点),
                "内存使用": self.内存使用.get(节点),
                "时间复杂度": self.复杂度估计.get(节点),
                "性能瓶颈": self._获取节点性能瓶颈(节点)
            }
            
            self.标记已分析(节点)
            return self.分析结果[节点._节点ID]
            
        except Exception as e:
            self.记录分析日志(f"性能分析失败: {str(e)}", "error")
            return {}
            
    def _分析执行时间(self, 节点: ast节点基础模型) -> None:
        """分析节点的执行时间"""
        try:
            # 执行多次以获取平均时间
            执行次数 = 5
            总时间 = 0
            
            for _ in range(执行次数):
                开始时间 = time.perf_counter()
                
                # 执行节点操作
                if hasattr(节点, '执行'):
                    节点.执行()
                    
                结束时间 = time.perf_counter()
                总时间 += (结束时间 - 开始时间)
                
            平均时间 = 总时间 / 执行次数
            self.执行时间[节点] = 平均时间
            self.资源使用统计["执行时间"]["总计"] += 平均时间
            
        except Exception as e:
            self.记录分析日志(f"执行时间分析失败: {str(e)}", "error")
            
    def _分析内存使用(self, 节点: ast节点基础模型) -> None:
        """分析节点的内存使用情况"""
        try:
            import sys
            import gc
            
            # 强制垃圾回收
            gc.collect()
            
            # 获取初始内存使用
            初始内存 = sys.getsizeof(节点)
            
            # 递归获取属性的内存使用
            for 属性名, 属性值 in vars(节点).items():
                try:
                    初始内存 += sys.getsizeof(属性值)
                except:
                    pass
                    
            self.内存使用[节点] = 初始内存
            self.资源使用统计["内存使用"]["总计"] += 初始内存
            
        except Exception as e:
            self.记录分析日志(f"内存使用分析失败: {str(e)}", "error")
            
    def _分析时间复杂度(self, 节点: ast节点基础模型) -> None:
        """分析节点的时间复杂度"""
        if not hasattr(节点, '_ast节点'):
            return
            
        class 复杂度分析器(ast.NodeVisitor):
            def __init__(self, 外部实例):
                self.外部实例 = 外部实例
                self.循环深度 = 0
                self.最高复杂度 = "O(1)"
                
            def visit_For(self, ast节点):
                self.循环深度 += 1
                self.generic_visit(ast节点)
                self.循环深度 -= 1
                self._更新复杂度()
                
            def visit_While(self, ast节点):
                self.循环深度 += 1
                self.generic_visit(ast节点)
                self.循环深度 -= 1
                self._更新复杂度()
                
            def _更新复杂度(self):
                if self.循环深度 == 0:
                    self.最高复杂度 = "O(1)"
                elif self.循环深度 == 1:
                    self.最高复杂度 = "O(n)"
                else:
                    self.最高复杂度 = f"O(n^{self.循环深度})"
                    
        分析器 = 复杂度分析器(self)
        分析器.visit(节点._ast节点)
        self.复杂度估计[节点] = 分析器.最高复杂度
        
    def _识别性能瓶颈(self, 节点: ast节点基础模型) -> None:
        """识别节点的性能瓶颈"""
        # 检查执行时间
        if 节点 in self.执行时间:
            执行时间 = self.执行时间[节点]
            if 执行时间 > 0.1:  # 超过100ms视为瓶颈
                self.性能瓶颈.append({
                    "节点模型": 节点._节点ID,
                    "类型": "执行时间",
                    "值": 执行时间,
                    "描述": "执行时间过长"
                })
                
        # 检查内存使用
        if 节点 in self.内存使用:
            内存使用量 = self.内存使用[节点]
            if 内存使用量 > 1024 * 1024:  # 超过1MB视为瓶颈
                self.性能瓶颈.append({
                    "节点模型": 节点._节点ID,
                    "类型": "内存使用",
                    "值": 内存使用量,
                    "描述": "内存使用过高"
                })
                
        # 检查时间复杂度
        if 节点 in self.复杂度估计:
            复杂度 = self.复杂度估计[节点]
            if 复杂度.startswith("O(n^") and int(复杂度[4:-1]) > 1:
                self.性能瓶颈.append({
                    "节点模型": 节点._节点ID,
                    "类型": "时间复杂度",
                    "值": 复杂度,
                    "描述": "时间复杂度过高"
                })
                
    def _获取节点性能瓶颈(self, 节点: ast节点基础模型) -> List[Dict[str, Any]]:
        """获取节点相关的性能瓶颈"""
        return [瓶颈 for 瓶颈 in self.性能瓶颈 if 瓶颈["节点模型"] == 节点._节点ID]
        
    def 获取性能报告(self) -> Dict[str, Any]:
        """获取完整的性能分析报告"""
        return {
            "执行时间统计": {
                "总执行时间": self.资源使用统计["执行时间"]["总计"],
                "平均执行时间": self.资源使用统计["执行时间"]["总计"] / len(self.执行时间) if self.执行时间 else 0
            },
            "内存使用统计": {
                "总内存使用": self.资源使用统计["内存使用"]["总计"],
                "平均内存使用": self.资源使用统计["内存使用"]["总计"] / len(self.内存使用) if self.内存使用 else 0
            },
            "复杂度分布": {节点._节点ID: 复杂度 for 节点, 复杂度 in self.复杂度估计.items()},
            "性能瓶颈": self.性能瓶颈
        }
        
    def 生成优化建议(self) -> List[Dict[str, str]]:
        """生成性能优化建议"""
        建议列表 = []
        
        for 瓶颈 in self.性能瓶颈:
            if 瓶颈["类型"] == "执行时间":
                建议列表.append({
                    "节点模型": 瓶颈["节点模型"],
                    "问题": "执行时间过长",
                    "建议": "考虑使用缓存或优化算法"
                })
            elif 瓶颈["类型"] == "内存使用":
                建议列表.append({
                    "节点模型": 瓶颈["节点模型"],
                    "问题": "内存使用过高",
                    "建议": "考虑使用生成器或减少中间结果存储"
                })
            elif 瓶颈["类型"] == "时间复杂度":
                建议列表.append({
                    "节点模型": 瓶颈["节点模型"],
                    "问题": "时间复杂度过高",
                    "建议": "考虑使用更高效的算法或数据结构"
                })
                
        return 建议列表
        
    def 重置(self) -> None:
        """重置分析器状态"""
        super().重置()
        self.执行时间.clear()
        self.内存使用.clear()
        self.复杂度估计.clear()
        self.性能瓶颈.clear()
        self.资源使用统计.clear()
        
    def __str__(self) -> str:
        """返回性能分析器的字符串表示"""
        return f"性能分析器(节点数={len(self.执行时间)}, 瓶颈数={len(self.性能瓶颈)})" 